package com.example.demo.tools;

import org.apache.commons.codec.digest.DigestUtils;

// 模拟md5加密
//MD5是一个安全的散列算法。
//输入两个不同的明文不会得到相同的输出值，根据输出值，不能得到原始的明文，即其过程不可逆；
//但是虽然不可逆，但是不是说就是安全的。因为自从出现彩虹表后，这样的密码也"不安全"。
//彩虹表：
//彩虹表就是一个庞大的、针对各种可能的字母组合预先计算好的哈希值的集合，不一定是针对MD5算法的，各种算法的都有。
//有了它可以快速的破解各类密码。越是复杂的密码，需要的彩虹表就越大，现在主流的彩虹表都是100G以上。
//而 MD5加密出来的密码是固定，比如： 123 在加密之后，为 asdasddasd
//只要有一个“密码库”记录了这一个组合，就可以根据 加密之后的密码，获取到 原本密码。
//所以说：彩虹表 天克 MD5 加密。
//不安全的原因：
//1、 暴力攻击速度很快
//2、 字典表很大
//3、 碰撞
//更安全的做法是加盐或者长密码等做法，让整个加密的字符串变的更长，破解时间变慢。
//密码学的应用安全，是建立在破解所要付出的成本远超出能得到的利益上的 。
//比如现在有一个条数据支持1万块，但是破解起来需要3年的时间。
//等到破解的时候，这个数据恐怕已经不值钱了！
//这种费力不讨好的事情，人家不会去做。
//这里我们介绍加盐的做法：
//盐是在每个密码中加入一些单词来变成一个新的密码，存入数据库当中。
//使用之前要添加依赖
//<!-- md5 依赖 -->
//<dependency>
//<groupId>commons-codec</groupId>
//<artifactId>commons-codec</artifactId>
//</dependency>
//<dependency>
//<groupId>org.apache.commons</groupId>
//<artifactId>commons-lang3</artifactId>
//<version>3.9</version>
//</dependency>
public class MD5Util {
    // 定义一个固定的盐值
    private static final String salt = "1b2i3t4e";

    // 定义一个 调用md5加密的方法
    public static String md5(String src) {
        return DigestUtils.md5Hex(src);
    }

    // 第一次加密(前端加密) 模拟前端自己加密 然后传到后端
    public static String inputPassToFormPass(String inputPass) {
        // 先对密码加盐
        String str = "" + salt.charAt(1) + salt.charAt(3) + inputPass + salt.charAt(5) +salt.charAt(6);
        // 再进行一次md5加密
        return md5(str);
    }


    // 第二次 MD5加密(服务器加密)
    // 前端加过密码 传给后端 然后后端进行二次加密
    public static String formPassToDBPass(String fromPass, String salt) {
        // 先对密码加盐
        String str = "" + salt.charAt(0) + salt.charAt(2) + fromPass + salt.charAt(5) + salt.charAt(4);

        // 然后再进行一次md5加密
        return md5(str);
    }


    // 上面两个函数一起调用
    public static String inputPassToDbPass(String inputPass, String saltDB) {
        String formPass = inputPassToFormPass(inputPass);// 第一次加密
        String dbPass = formPassToDBPass(formPass, saltDB); // 第二次加密
        return dbPass;
    }

    // 结果展示
    public static void main(String[] args) {
        System.out.println("对用户进行第一次密码加密" + inputPassToFormPass("123456"));
        System.out.println("对用户进行第二次密码加密" + formPassToDBPass(inputPassToFormPass("123456"), "1b2i3t4e"));

        System.out.println("对用户进行二次密码加密  " + inputPassToDbPass("123456", salt));
    }
//    打印结果：
//对用户进行第一次密码加密72f3a23068b59100e599bc181057cb4c
//对用户进行第二次密码加密471491bed89c4c67af7688cec111cc82
//对用户进行二次密码加密  471491bed89c4c67af7688cec111cc82

//不管运行多少次，这个密码是规定的。因为这里没有用随机盐值。当密码长度很大，
//盐值也是随机的情况下，密码的强度也加大了。破解成本也增加了。
//所以，最好的加密方式，就是将我们的 固定盐，修改成 随机盐。
//这也是为什么我们在某个平台创建账户，官方要求我们的密码是 数字和字母混合的，而且长度不能低于某个界限。
//就是为了提高我们密码的安全性
}
